/*
 * @brief Common ring buffer support functions
 *
 * @note
 * Copyright(C) NXP Semiconductors, 2012
 * All rights reserved.
 *
 * @par
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * LPC products.  This software is supplied "AS IS" without any warranties of
 * any kind, and NXP Semiconductors and its licensor disclaim any and
 * all warranties, express or implied, including all implied warranties of
 * merchantability, fitness for a particular purpose and non-infringement of
 * intellectual property rights.  NXP Semiconductors assumes no responsibility
 * or liability for the use of the software, conveys no license or rights under any
 * patent, copyright, mask work right, or any other intellectual property rights in
 * or to any products. NXP Semiconductors reserves the right to make changes
 * in the software without notification. NXP Semiconductors also makes no
 * representation or warranty that such application will be suitable for the
 * specified use without further testing or modification.
 *
 * @par
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, under NXP Semiconductors' and its
 * licensor's relevant copyrights in the software, without fee, provided that it
 * is used in conjunction with NXP Semiconductors microcontrollers.  This
 * copyright, permission, and disclaimer notice must appear in all copies of
 * this code.
 */

#include "ring_buffer.h"

/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Private functions
 ****************************************************************************/

/*****************************************************************************
 * Public functions
 ****************************************************************************/

/* Initialize ring buffer */
void RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count)
{
	RingBuff->bufferBase = RingBuff->bufferIn = RingBuff->bufferOut = buffer;
	RingBuff->bufferLast = RingBuff->bufferBase + (itemSize * count);
	RingBuff->count = count;
	RingBuff->itemSize = itemSize;
	RingBuff->used = 0;
}

/* Return empty status of ring buffer */
bool RingBuffer_Insert8(RINGBUFF_T *RingBuff, uint8_t data8)
{
	bool full = RingBuffer_IsFull(RingBuff);

	if (!full) {
		*RingBuff->bufferIn = data8;
		RingBuff->used++;
		RingBuff->bufferIn++;
		if (RingBuff->bufferIn >= RingBuff->bufferLast) {
			RingBuff->bufferIn = RingBuff->bufferBase;
		}
	}

	return (bool) !full;
}

/* Insert 16-bit value in ring buffer */
bool RingBuffer_Insert16(RINGBUFF_T *RingBuff, uint16_t data16)
{
	bool full = RingBuffer_IsFull(RingBuff);

	if (!full) {
		uint16_t *buff16 = (uint16_t *) RingBuff->bufferIn;
		*buff16 = data16;
		RingBuff->used++;
		buff16++;
		RingBuff->bufferIn = (uint8_t *) buff16;
		if (RingBuff->bufferIn >= RingBuff->bufferLast) {
			RingBuff->bufferIn = RingBuff->bufferBase;
		}
	}

	return (bool) !full;
}

/* Insert 32-bit value in ring buffer */
bool RingBuffer_Insert32(RINGBUFF_T *RingBuff, uint32_t data32)
{
	bool full = RingBuffer_IsFull(RingBuff);

	if (!full) {
		uint32_t *buff32 = (uint32_t *) RingBuff->bufferIn;
		*buff32 = data32;
		RingBuff->used++;
		buff32++;
		RingBuff->bufferIn = (uint8_t *) buff32;
		if (RingBuff->bufferIn >= RingBuff->bufferLast) {
			RingBuff->bufferIn = RingBuff->bufferBase;
		}
	}

	return (bool) !full;
}

/* Pop a 8-bit value from the ring buffer */
bool RingBuffer_Pop8(RINGBUFF_T *RingBuff, uint8_t *data8)
{
	bool empty = RingBuffer_IsEmpty(RingBuff);

	if (!empty) {
		*data8 = *RingBuff->bufferOut;
		RingBuff->used--;
		RingBuff->bufferOut++;
		if (RingBuff->bufferOut >= RingBuff->bufferLast) {
			RingBuff->bufferOut = RingBuff->bufferBase;
		}
	}

	return (bool) !empty;
}

/* Pop a 16-bit value from the ring buffer */
bool RingBuffer_Pop16(RINGBUFF_T *RingBuff, uint16_t *data16)
{
	bool empty = RingBuffer_IsEmpty(RingBuff);

	if (!empty) {
		uint16_t *buff16 = (uint16_t *) RingBuff->bufferOut;
		*data16 = *buff16;
		RingBuff->used--;
		buff16++;
		RingBuff->bufferOut = (uint8_t *) buff16;
		if (RingBuff->bufferOut >= RingBuff->bufferLast) {
			RingBuff->bufferOut = RingBuff->bufferBase;
		}
	}

	return (bool) !empty;
}

/* Pop a 32-bit value from the ring buffer */
bool RingBuffer_Pop32(RINGBUFF_T *RingBuff, uint32_t *data32)
{
	bool empty = RingBuffer_IsEmpty(RingBuff);

	if (!empty) {
		uint32_t *buff32 = (uint32_t *) RingBuff->bufferOut;
		*data32 = *buff32;
		RingBuff->used--;
		data32++;
		RingBuff->bufferOut = (uint8_t *) data32;
		if (RingBuff->bufferOut >= RingBuff->bufferLast) {
			RingBuff->bufferOut = RingBuff->bufferBase;
		}
	}

	return (bool) !empty;
}
